from django.shortcuts import render, get_object_or_404, redirect
from django.contrib.auth.mixins import LoginRequiredMixin, PermissionRequiredMixin
from django.http import HttpResponseRedirect, JsonResponse
from django.urls import reverse, reverse_lazy
from django.contrib.auth.decorators import login_required, permission_required
import datetime
from django.views.generic.edit import CreateView, UpdateView, DeleteView
from django import forms
from django.contrib.admin.views.decorators import staff_member_required
from .models import Book, Author, BookInstance, Genre, BookRating, BookReview, BookLike
from django.db.models import Count
from django.contrib import messages
from django.utils import timezone
from .forms import BookForm
from django.views.decorators.csrf import csrf_exempt
from openai import OpenAI

# Create your views here.

@login_required
def index(request):
    """
    View function for home page of site.
    """
    # 基于会话的访问计数器
    num_visits = request.session.get('num_visits', 0)
    request.session['num_visits'] = num_visits + 1
    # Generate counts of some of the main objects
    num_books = Book.objects.count()
    num_instances = BookInstance.objects.count()
    # Available books (status = 'a')
    num_instances_available = BookInstance.objects.filter(status__exact='a').count()
    num_authors = Author.objects.count()  # The 'all()' is implied by default.
    num_borrowed = BookInstance.objects.filter(status='o').count()
    num_likes = BookLike.objects.count()
    num_ratings = BookRating.objects.count()

    # Render the HTML template index.html with the data in the context variable
    context = {
        'num_books': num_books,
        'num_instances': num_instances,
        'num_instances_available': num_instances_available,
        'num_authors': num_authors,
        'num_visits': num_visits + 1,
        'num_borrowed': num_borrowed,
        'num_likes': num_likes,
        'num_ratings': num_ratings,
    }
    return render(request, 'catalog/index.html', context=context)

from django.views import generic

class BookListView(generic.ListView):
    model = Book
    paginate_by = 10

class BookDetailView(generic.DetailView):
    model = Book
    template_name = 'catalog/book_detail.html'
    def get_context_data(self, **kwargs):
        context = super().get_context_data(**kwargs)
        context['reviews'] = self.object.reviews.all().order_by('-created_at')
        user = self.request.user
        context['liked_by_user'] = False
        if user.is_authenticated:
            context['liked_by_user'] = self.object.likes.filter(user=user).exists()
        return context

class AuthorListView(generic.ListView):
    model = Author
    paginate_by = 10

class AuthorDetailView(generic.DetailView):
    model = Author

class LoanedBooksByUserListView(LoginRequiredMixin, generic.ListView):
    """显示当前用户借阅的所有书"""
    model = BookInstance
    template_name = 'catalog/bookinstance_list_borrowed_user.html'
    paginate_by = 10

    def get_queryset(self):
        return BookInstance.objects.filter(borrower=self.request.user).filter(status__exact='o').order_by('due_back')

class RenewBookForm(forms.Form):
    renewal_date = forms.DateField(help_text="输入一个介于今天和4周内的日期")

    def clean_renewal_date(self):
        data = self.cleaned_data['renewal_date']
        if data < datetime.date.today():
            raise forms.ValidationError('无效日期 - 早于今天')
        if data > datetime.date.today() + datetime.timedelta(weeks=4):
            raise forms.ValidationError('无效日期 - 超过4周')
        return data

@permission_required('catalog.can_mark_returned')
def renew_book_librarian(request, pk):
    book_instance = get_object_or_404(BookInstance, pk=pk)
    if request.method == 'POST':
        form = RenewBookForm(request.POST)
        if form.is_valid():
            book_instance.due_back = form.cleaned_data['renewal_date']
            book_instance.save()
            return HttpResponseRedirect(reverse('all-borrowed'))
    else:
        proposed_renewal_date = datetime.date.today() + datetime.timedelta(weeks=3)
        form = RenewBookForm(initial={'renewal_date': proposed_renewal_date})
    return render(request, 'catalog/book_renew_librarian.html', {'form': form, 'book_instance': book_instance})

class AuthorCreateView(LoginRequiredMixin, generic.CreateView):
    model = Author
    fields = '__all__'
    template_name = 'catalog/author_form.html'

class AuthorUpdateView(LoginRequiredMixin, generic.UpdateView):
    model = Author
    fields = '__all__'
    template_name = 'catalog/author_form.html'

class AuthorDeleteView(LoginRequiredMixin, generic.DeleteView):
    model = Author
    success_url = '/catalog/authors/'
    template_name = 'catalog/author_confirm_delete.html'

class LoanedBooksAllListView(PermissionRequiredMixin, generic.ListView):
    """显示所有被借出的书（仅限有 can_mark_returned 权限的用户）"""
    model = BookInstance
    permission_required = 'catalog.can_mark_returned'
    template_name = 'catalog/bookinstance_list_borrowed_all.html'
    paginate_by = 10

    def get_queryset(self):
        return BookInstance.objects.filter(status__exact='o').order_by('due_back')

class BookCreateView(LoginRequiredMixin, generic.CreateView):
    model = Book
    fields = '__all__'
    template_name = 'catalog/book_form.html'

class BookUpdateView(LoginRequiredMixin, generic.UpdateView):
    model = Book
    fields = '__all__'
    template_name = 'catalog/book_form.html'

class BookDeleteView(LoginRequiredMixin, generic.DeleteView):
    model = Book
    success_url = '/catalog/books/'
    template_name = 'catalog/book_confirm_delete.html'

class AuthorCreate(LoginRequiredMixin, CreateView):
    model = Author
    fields = '__all__'
    initial = {'date_of_death': '2020-01-01'}

class AuthorUpdate(UpdateView):
    model = Author
    fields = ['first_name', 'last_name', 'date_of_birth', 'date_of_death']

class AuthorDelete(DeleteView):
    model = Author
    success_url = reverse_lazy('authors')

@login_required
def mybooks(request):
    borrowed_books = BookInstance.objects.filter(borrower=request.user).filter(status__exact='o')
    return render(request, 'catalog/mybooks.html', {'borrowed_books': borrowed_books})

def authors(request):
    authors = Author.objects.all()
    return render(request, 'catalog/authors.html', {'authors': authors})

def author_detail(request, pk):
    author = get_object_or_404(Author, pk=pk)
    return render(request, 'catalog/author_detail.html', {'author': author})

@staff_member_required
def borrowed(request):
    all_borrowed = LoanedBook.objects.all()
    return render(request, 'catalog/borrowed.html', {'all_borrowed': all_borrowed})

@login_required
def book_create(request):
    if request.method == 'POST':
        form = BookForm(request.POST)
        if form.is_valid():
            form.save()
            return redirect('books')
    else:
        form = BookForm()
    return render(request, 'catalog/book_form.html', {'form': form})

@login_required
def rate_book(request, pk):
    book = get_object_or_404(Book, pk=pk)
    if request.method == 'POST':
        score = int(request.POST.get('score', 0))
        if 1 <= score <= 5:
            rating, created = BookRating.objects.update_or_create(
                book=book, user=request.user,
                defaults={'score': score}
            )
    return redirect('book-detail', pk=pk)

@login_required
def review_book(request, pk):
    book = get_object_or_404(Book, pk=pk)
    if request.method == 'POST':
        content = request.POST.get('content', '').strip()
        if content:
            BookReview.objects.create(book=book, user=request.user, content=content)
    return redirect('book-detail', pk=pk)

def book_rank(request):
    # 统计每本书被借出的次数
    books = Book.objects.annotate(borrow_count=Count('bookinstance')).order_by('-borrow_count')[:10]
    return render(request, 'catalog/book_rank.html', {'books': books})

@login_required
def like_book(request, pk):
    book = get_object_or_404(Book, pk=pk)
    user = request.user
    today = timezone.now().date()
    # 查询今天该用户的点赞数
    like_count = BookLike.objects.filter(user=user, created_at__date=today).count()
    if like_count >= 10:
        messages.warning(request, "您今天的点赞次数已达上限（10次）！")
        return redirect('book-detail', pk=pk)
    BookLike.objects.create(book=book, user=user)
    return redirect('book-detail', pk=pk)

@login_required
def borrow_book(request, pk):
    book = get_object_or_404(Book, pk=pk)
    # 检查该用户是否已借出该书且未归还
    bookinst = BookInstance.objects.filter(book=book, borrower=request.user, status='o').first()
    if bookinst:
        messages.error(request, '书籍借出中！')
        return redirect('book-detail', pk=pk)
    # 创建借阅记录，精确到分钟
    now = timezone.now()
    due = now + datetime.timedelta(weeks=3)
    bookinst = BookInstance.objects.create(
        id=f'{book.pk}_{request.user.pk}_{now.strftime("%Y%m%d%H%M%S")}',
        book=book,
        imprint='借阅',
        due_back=due,
        borrower=request.user,
        status='o',
    )
    messages.success(request, '借阅成功！')
    return redirect('my-borrowed')

@login_required
def return_book(request, pk):
    from .models import BookInstance
    bookinst = get_object_or_404(BookInstance, pk=pk, borrower=request.user, status='o')
    bookinst.status = 'a'
    bookinst.borrower = None
    bookinst.save()
    messages.success(request, '归还成功！')
    return redirect('my-borrowed')

@login_required
def account_center(request):
    """
    账号中心视图，显示当前用户信息。
    """
    return render(request, 'catalog/account.html')

# 接入个人 DeepSeek API Key
client = OpenAI(
    api_key="sk-bbb42272075c45ccb55fdf456a862227",
    base_url="https://api.deepseek.com/v1"
)

@csrf_exempt
def ai_chat(request):
    if request.method == 'POST':
        user_input = request.POST.get('message', '')
        # 你可以根据输入内容自定义 prompt
        try:
            response = client.chat.completions.create(
                model="deepseek-chat",
                messages=[
                    {"role": "system", "content": "你是一个专业的图书馆AI助手，擅长知识问答、书籍简介和模拟名人对话。"},
                    {"role": "user", "content": user_input}
                ],
                temperature=0.7,
                max_tokens=1000
            )
            ai_reply = response.choices[0].message.content
        except Exception as e:
            ai_reply = f"AI服务出错：{str(e)}"
        return JsonResponse({'reply': ai_reply})
    return JsonResponse({'reply': '仅支持POST请求'})

